//
//	MiscLogSliderCell.h -- a SliderCell with logarithmic transfer function
//		Written by Don Yacktman, Copyright (c) 1994 by Don Yacktman.
//				Version 1.0  All rights reserved.
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	


#import "MiscLogSliderCell.h"
#import <math.h>
#import <sys/param.h>

@interface MiscLogSliderCell(Private)

- _setLB;

@end


@implementation MiscLogSliderCell

- init
{
	id ret = [super init];
	base = 10;
	realMax = 1000;
	realMin = 1;
	[self _setLB];
	[self setDoubleValue:1];
	return ret;
}

- _setLB
{
	_lbx = log(realMax) / log(base);
	_lbn = log(realMin) / log(base);
	return self;
}

- (double)base { return base; }
- (double)maxValue  { return realMax; }
- (double)minValue  { return realMin; }

// ***** need to implement range checking to make sure we are using sane numbers here!
- setBase:(double)newBase
{
	base = MAX(2, newBase);
	[self _setLB];
	return self;
}

- setMaxValue:(double)aDouble
{
	realMax = MAX(1, aDouble);
	[self _setLB];
	return self;
}

- setMinValue:(double)aDouble
{
	realMin = MAX(1, aDouble);
	[self _setLB];
	return self;
}

// -doubleValue returns the right value and does all the work; the other
// methods generate their values from the return from -doubleValue.

// ***** These need to be implemented properly.
- (const char *)stringValue { return [super stringValue]; }
- setStringValue:(const char *)aString { return [super setStringValue:aString]; }

// These are finished:
- (int)intValue { return [self doubleValue]; }
- setIntValue:(int)anInt { return [self setDoubleValue:anInt]; }
- (float)floatValue { return [self doubleValue]; }
- setFloatValue:(float)aFloat { return [self setDoubleValue:aFloat]; }

- (double)doubleValue
{
	return pow(base, (_lbn + [super doubleValue] * (_lbx - _lbn)));
}

- setDoubleValue:(double)aDouble
{
	return [super setDoubleValue:
			(((log(aDouble) / log(base)) - _lbn) / (_lbx - _lbn))];
}

- read:(NXTypedStream *)stream
{
	[super read:stream];
	NXReadTypes(stream, "ddd", &base, &realMax, &realMin);
	[self _setLB];
	return self;
}

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteTypes(stream, "ddd", &base, &realMax, &realMin);
	return self;
}

- awake
{ // this is all just "to be sure"
	if (base < 2) base = 1;
	if (realMax < 1) realMax = 1;
	if (realMin < 1) realMin = 1;
	[self _setLB];
	return [super awake];
}

@end
